#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

import os

from exchange import log
from exchange.commons.const import ExchangeJobInfo, PathSymbol, ExchangeDatabaseCopyStatus, ParamConstant
from exchange.commons.exchange_function_tool import log_start_end, out_result_with_job_info, \
    progress_notify_with_job_info
from common.common import execute_cmd
from exchange.commons.exchange_exception import ExchangeInternalException
from exchange.commons.powershell import PS_LOC, TIMEOUT
from exchange.commons.common import output_execution_result_ex
from exchange.restore.restore_param_parser import RestoreParamParser
from exchange.restore.exchange_server_api.exchange_cmd_client import ExchangeCmdClient


# Exchange备份后置任务基类
class ExchangeRestorePost:
    def __init__(self, pid, param):
        self._pid = pid
        self._param = param
        self._exchange_cmd_client = ExchangeCmdClient(pid)

    @log_start_end()
    @out_result_with_job_info()
    @progress_notify_with_job_info()
    def do_post_task(self, job_info: ExchangeJobInfo):
        try:
            file_path = os.path.join(ParamConstant.PARAM_FILE_PATH, "is_recovered")
            output_execution_result_ex(file_path, {"is_recovered": True})
            log.info(f"Write is_recovered file successful.")
        except Exception as err:
            log.error(f"Write is_recovered file failed, err: {err}.")
            return False
        # 后置任务, 如果恢复任务失败, 根据参数判断是否自动装入恢复之前的数据库
        auto_mount = RestoreParamParser.get_auto_mount(self._param)
        if "true" == auto_mount:
            log.info("Begin auto mount database.")
            database_name_maps = RestoreParamParser.get_database_name_maps(self._param)
            for database_name_map in database_name_maps:
                database_name = database_name_map.get("source_target_name", "")
                dismount_status = self.check_exchange_database_dismounted_status(database_name)
                if not dismount_status:
                    continue
                try:
                    self._exchange_cmd_client.mount_exchange_database(database_name)
                    log.info(f"Auto mount database: {database_name} success.")
                except ExchangeInternalException:
                    log.error(f"Auto mount database: {database_name} failed.")
                    return False
        return True

    def check_exchange_database_dismounted_status(self, database_name):
        # 检查活动数据库副本卸载状态
        log.info(f'Check exchange database :{database_name} dismount status')
        # 生成指定副本名称（database_name\server_name）
        code, hostname, err = execute_cmd([PS_LOC, "hostname"], timeout=TIMEOUT, cmd_array_flag=True)
        hostname = hostname.strip()
        copy_name = database_name + PathSymbol.SLASHES + hostname
        log.info(f'Check exchange database copy:{copy_name} dismount status')
        # 查询数据库对应副本
        copies = self._exchange_cmd_client.get_exchange_database_copies(copy_name)
        if len(copies) != 1:
            log.error(f"Can not find or multi copy:{copy_name}")
            return False
        # 判断活动副本状态是否为dismounted
        if ExchangeDatabaseCopyStatus.DISMOUNTED != copies[0].get("Status").get("value"):
            log.error("Exchange database still mounted")
            return False
        log.info(f'Exchange database :{database_name} is dismounted')
        return True
